import { getRedisClient } from '../database/redis';

/**
 * Redis 键前缀常量
 */
export const REDIS_KEYS = {
  // 用户相关
  USER_SESSION: 'user:session:',
  USER_TOKEN: 'user:token:',
  USER_PERMISSIONS: 'user:permissions:',
  
  // 缓存相关
  CACHE_NEWS: 'cache:news:',
  CACHE_CATEGORY: 'cache:category:',
  CACHE_USER: 'cache:user:',
  
  // 统计相关
  STATS_VIEWS: 'stats:views:',
  STATS_VISITS: 'stats:visits:',
  
  // 锁相关
  LOCK_UPDATE: 'lock:update:',
  LOCK_DELETE: 'lock:delete:',
} as const;

/**
 * 基础 Redis 操作类
 */
export class RedisService {
  /**
   * 获取 Redis 客户端
   */
  private async getClient() {
    return await getRedisClient();
  }

  /**
   * 设置键值对
   */
  async set(key: string, value: any, expireSeconds?: number): Promise<void> {
    try {
      const client = await this.getClient();
      const serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
      if (expireSeconds) {
        await client.setex(key, expireSeconds, serializedValue);
      } else {
        await client.set(key, serializedValue);
      }
    } catch (error) {
      console.error('Redis SET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 获取值
   */
  async get(key: string): Promise<any> {
    try {
      const client = await this.getClient();
      const value = await client.get(key);
      if (value === null) return null;
      return value;
    } catch (error) {
      console.error('Redis GET 操作失败:', error);
      throw error;
    }
  }
  async getObject(key: string): Promise<any> {
    try {
      const client = await this.getClient();
      const value = await client.get(key);
      if (value === null) return null;
      
      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('Redis GET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 删除键
   */
  async del(key: string): Promise<number> {
    try {
      const client = await this.getClient();
      return await client.del(key);
    } catch (error) {
      console.error('Redis DEL 操作失败:', error);
      throw error;
    }
  }

  /**
   * 检查键是否存在
   */
  async exists(key: string): Promise<boolean> {
    try {
      const client = await this.getClient();
      const result = await client.exists(key);
      return result === 1;
    } catch (error) {
      console.error('Redis EXISTS 操作失败:', error);
      throw error;
    }
  }

  /**
   * 设置过期时间
   */
  async expire(key: string, seconds: number): Promise<boolean> {
    try {
      const client = await this.getClient();
      const result = await client.expire(key, seconds);
      return result === 1;
    } catch (error) {
      console.error('Redis EXPIRE 操作失败:', error);
      throw error;
    }
  }

  /**
   * 获取剩余过期时间
   */
  async ttl(key: string): Promise<number> {
    try {
      const client = await this.getClient();
      return await client.ttl(key);
    } catch (error) {
      console.error('Redis TTL 操作失败:', error);
      throw error;
    }
  }

  /**
   * 批量获取
   */
  async mget(keys: string[]): Promise<any[]> {
    try {
      const client = await this.getClient();
      const values = await client.mget(keys);
      return values.map((value: any) => {
        if (value === null) return null;
        try {
          return JSON.parse(value);
        } catch {
          return value;
        }
      });
    } catch (error) {
      console.error('Redis MGET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 批量设置
   */
  async mset(keyValuePairs: Record<string, any>, expireSeconds?: number): Promise<void> {
    try {
      const client = await this.getClient();
      const pipeline = client.pipeline();
      
      for (const [key, value] of Object.entries(keyValuePairs)) {
        const serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
        if (expireSeconds) {
          pipeline.setex(key, expireSeconds, serializedValue);
        } else {
          pipeline.set(key, serializedValue);
        }
      }
      
      await pipeline.exec();
    } catch (error) {
      console.error('Redis MSET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 哈希表操作 - 设置字段
   */
  async hset(key: string, field: string, value: any): Promise<number> {
    try {
      const client = await this.getClient();
      const serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
      return await client.hset(key, field, serializedValue);
    } catch (error) {
      console.error('Redis HSET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 哈希表操作 - 获取字段
   */
  async hget(key: string, field: string): Promise<any> {
    try {
      const client = await this.getClient();
      const value = await client.hget(key, field);
      if (value === null) return null;
      
      try {
        return JSON.parse(value);
      } catch {
        return value;
      }
    } catch (error) {
      console.error('Redis HGET 操作失败:', error);
      throw error;
    }
  }

  /**
   * 哈希表操作 - 获取所有字段
   */
  async hgetall(key: string): Promise<Record<string, any>> {
    try {
      const client = await this.getClient();
      const result = await client.hgetall(key);
      const parsed: Record<string, any> = {};
      
      for (const [field, value] of Object.entries(result)) {
        try {
          parsed[field] = JSON.parse(value as string);
        } catch {
          parsed[field] = value;
        }
      }
      
      return parsed;
    } catch (error) {
      console.error('Redis HGETALL 操作失败:', error);
      throw error;
    }
  }

  /**
   * 列表操作 - 左侧推入
   */
  async lpush(key: string, ...values: any[]): Promise<number> {
    try {
      const client = await this.getClient();
      const serializedValues = values.map((value: any) => 
        typeof value === 'string' ? value : JSON.stringify(value)
      );
      return await client.lpush(key, ...serializedValues);
    } catch (error) {
      console.error('Redis LPUSH 操作失败:', error);
      throw error;
    }
  }

  /**
   * 列表操作 - 右侧推入
   */
  async rpush(key: string, ...values: any[]): Promise<number> {
    try {
      const client = await this.getClient();
      const serializedValues = values.map((value: any) => 
        typeof value === 'string' ? value : JSON.stringify(value)
      );
      return await client.rpush(key, ...serializedValues);
    } catch (error) {
      console.error('Redis RPUSH 操作失败:', error);
      throw error;
    }
  }

  /**
   * 列表操作 - 获取范围
   */
  async lrange(key: string, start: number, stop: number): Promise<any[]> {
    try {
      const client = await this.getClient();
      const values = await client.lrange(key, start, stop);
      return values.map((value: any) => {
        try {
          return JSON.parse(value);
        } catch {
          return value;
        }
      });
    } catch (error) {
      console.error('Redis LRANGE 操作失败:', error);
      throw error;
    }
  }

  /**
   * 集合操作 - 添加成员
   */
  async sadd(key: string, ...members: any[]): Promise<number> {
    try {
      const client = await this.getClient();
      const serializedMembers = members.map((member: any) => 
        typeof member === 'string' ? member : JSON.stringify(member)
      );
      return await client.sadd(key, ...serializedMembers);
    } catch (error) {
      console.error('Redis SADD 操作失败:', error);
      throw error;
    }
  }

  /**
   * 集合操作 - 获取所有成员
   */
  async smembers(key: string): Promise<any[]> {
    try {
      const client = await this.getClient();
      const members = await client.smembers(key);
      return members.map((member: any) => {
        try {
          return JSON.parse(member);
        } catch {
          return member;
        }
      });
    } catch (error) {
      console.error('Redis SMEMBERS 操作失败:', error);
      throw error;
    }
  }

  /**
   * 计数器操作 - 增加
   */
  async incr(key: string): Promise<number> {
    try {
      const client = await this.getClient();
      return await client.incr(key);
    } catch (error) {
      console.error('Redis INCR 操作失败:', error);
      throw error;
    }
  }

  /**
   * 计数器操作 - 按指定值增加
   */
  async incrby(key: string, increment: number): Promise<number> {
    try {
      const client = await this.getClient();
      return await client.incrby(key, increment);
    } catch (error) {
      console.error('Redis INCRBY 操作失败:', error);
      throw error;
    }
  }

  /**
   * 搜索键
   */
  async keys(pattern: string): Promise<string[]> {
    try {
      const client = await this.getClient();
      return await client.keys(pattern);
    } catch (error) {
      console.error('Redis KEYS 操作失败:', error);
      throw error;
    }
  }

  /**
   * 清空当前数据库
   */
  async flushdb(): Promise<void> {
    try {
      const client = await this.getClient();
      await client.flushdb();
    } catch (error) {
      console.error('Redis FLUSHDB 操作失败:', error);
      throw error;
    }
  }
}

// 创建全局 Redis 服务实例
export const redisService = new RedisService(); 